package td.pt.widget;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import td.client.ClientState;
import td.domain.Thought;
import td.pt.event.HideAllPopupsEvent;
import td.pt.event.HideAllPopupsEvent.HideAllPopupsHandler;
import td.pt.event.ReferenceThoughtsEvent;
import td.pt.event.UseReferenceNavigationEvent;
import td.pt.event.UseReferenceNavigationEvent.UseReferenceNavigationHandler;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.PopupView;
import com.gwtplatform.mvp.client.PresenterWidget;
import com.gwtplatform.mvp.client.proxy.RevealRootPopupContentEvent;

public class ReferenceListingPopupPresenter extends
		PresenterWidget<ReferenceListingPopupPresenter.MyView> {

	public interface MyView extends PopupView {
		public CellTable<Thought> getCellTable();

		public SimplePager getPager();

		public Button getUseReference();

		public Button getCopyReference();

		public Button getClose();

		public Label getTitle();

		public void refresh();

		public MultiSelectionModel<Thought> getSelectionModel();

		ListDataProvider<Thought> getDataProvider();
	}

	@Inject
	ClientState state;

	UseReferenceNavigationHandler useReferenceNavigationHandler = new UseReferenceNavigationHandler() {

		@Override
		public void onUseReferenceNavigation(UseReferenceNavigationEvent event) {
			Thought thought = event.getThought();
			String title = null;
			switch (event.getReferenceNavigationType()) {
			case ADD_REFERENCE_TO_THOUGHT:
				title = "List of active References pending to be cited by your Thoughts";
				refresh(state.getThinker().getActiveReferences(), true);
				break;
			case VIEW_REFERENCED_BY_THOUGHT:
				title = "List of Thoughts referenced by this Thought";
				refresh(thought.getReferencedThoughts(), false);
				break;
			case VIEW_REFERENCES_OF_THOUGHT:
				title = "List of Thoughts referencing this Thought";
				refresh(thought.getReferencingThoughts(), false);
				break;
			}
			ReferenceListingPopupPresenter.this.getView().getTitle()
					.setText(title);
			RevealRootPopupContentEvent.fire(event.getSource(),
					ReferenceListingPopupPresenter.this);
		}
	};

	HideAllPopupsHandler hideAllPopupsHandler = new HideAllPopupsHandler() {

		@Override
		public void onHideAllPopups(HideAllPopupsEvent event) {
			ReferenceListingPopupPresenter.this.getView().hide();
		}
	};

	@Inject
	public ReferenceListingPopupPresenter(final EventBus eventBus,
			final MyView view) {
		super(eventBus, view);
	}

	@Override
	protected void onBind() {
		super.onBind();
		registerHandler(getEventBus()
				.addHandler(UseReferenceNavigationEvent.TYPE,
						useReferenceNavigationHandler));
		registerHandler(getEventBus().addHandler(HideAllPopupsEvent.TYPE,
				hideAllPopupsHandler));
		getView().getCopyReference().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				Set<Thought> thoughts = validateSelection();
				if (thoughts != null) {
					ReferenceThoughtsEvent referenceAThoughtEvent = new ReferenceThoughtsEvent(
							thoughts);
					getEventBus().fireEvent(referenceAThoughtEvent);
					getView().hide();
				}
			}
		});
		getView().getUseReference().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				Set<Thought> thoughts = validateSelection();
				if (thoughts != null) {
					for (Thought thought : thoughts) {
						state.getThinker().getActiveReferences()
								.remove(thought);
					}
					ReferenceThoughtsEvent referenceAThoughtEvent = new ReferenceThoughtsEvent(
							thoughts);
					getEventBus().fireEvent(referenceAThoughtEvent);
					getView().hide();
				}
			}
		});
		getView().getClose().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getView().hide();
			}
		});
	}

	private Set<Thought> validateSelection() {
		Set<Thought> thoughts = getView().getSelectionModel().getSelectedSet();
		if (thoughts == null || state.getThinker().getDraftReferences() == null) {
			return thoughts;
		}
		List<Thought> thougthtsToRemove = new ArrayList<Thought>();
		StringBuilder removedThoughts = new StringBuilder();
		for (Thought thought : thoughts) {
			if (state.getThinker().getDraftReferences().contains(thought)) {
				removedThoughts.append(" '");
				removedThoughts.append(thought.getTitle());
				removedThoughts.append("'");
				thougthtsToRemove.add(thought);
			}
		}
		for (Thought thoughtToRemove : thougthtsToRemove) {
			thoughts.remove(thoughtToRemove);
		}
		if (thoughts.size() < 1) {
			Window.alert("All selected Thoughts are already referenced in this Thought.");
			return null;
		}
		if (thougthtsToRemove.size() > 0) {
			Window.alert("Following selected Thoughts are already referenced in this Thought:"
					+ removedThoughts.toString());
		}
		return thoughts;
	}

	@Override
	protected void onReveal() {
		super.onReveal();
	}

	private void refresh(List<Thought> thoughts, boolean canEdit) {
		getView().getCopyReference().setVisible(canEdit);
		getView().getUseReference().setVisible(canEdit);
		getView().getCellTable().setRowData(thoughts);
		getView().getCellTable().setPageSize(12);
		getView().getDataProvider().getList().clear();
		getView().getDataProvider().getList().addAll(thoughts);
		getView().refresh();
	}
}
